from khronos.des import *
from khronos.des.primitives import *
from khronos.utils import *

class Emitter(object):
    def __init__(self, *signals):
        self.listeners = dict()
        if len(signals) > 0:
            self.add(*signals)
            
    def add(self, *signals):
        for signal in signals:
            if signal not in self.listeners:
                self.listeners[signal] = PQueue()
                
    def listen(self, signal, who, callback, priority=0.0):
        if signal not in self.listeners:
            self.add(signal)
        self.listeners[signal].insert((who, callback), priority)
        
    @Chain
    def emit(self, signal, *args, **kwargs):
        for callbacks, priority in self.listeners[signal].iterlists_descending():
            for who, callback in callbacks:
                who.execute(callback(signal, *args, **kwargs))
            if len(callbacks) == 1:
                yield who.action.observe()
            else:
                yield And(*[who.action.observe() for who, _ in callbacks])
                
class Machine(Process):
    def constructor(self, buffer):
        self.buffer = buffer
        
    def reset(self):
        self.signals = Emitter()
        
    @Chain
    def initialize(self):
        pass
        